package org.xmlpull.v1;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

/**
 * Define an interface to serialization（序列化） of XML Infoset（信息模型）.
 * This interface abstracts away if serialized XML is XML 1.0 compatible text or
 * 如果序列化XML是兼容XML 1.0的文本，则此接口将被抽象化
 * other formats of XML 1.0 serializations (such as binary XML for example with WBXML).
 *1.0其他格式的XML序列化(例如二进制XML WBXML)。
 * <p><b>PLEASE NOTE:</b>
 * This interface will be part of XmlPull 1.2 API.
 * 该接口将Xml拉1.2 API的一部分。
 * It is included as basis for discussion. It may change in any way.
 *它是作为讨论的依据。它可能会改变
 * <p>Exceptions that may be thrown are: IOException or runtime exception
 * 它是作为讨论的依据。它可能会改变
 * (more runtime exceptions can be thrown but are not declared and as such have no semantics defined for this interface):
 * (更可以抛出运行时异常但不宣布,因此没有语义为这个接口定义)
 * <ul>
 * <li><em>IllegalArgumentException</em> - for almost all methods to signal that argument is illegal
 * 几乎所有的方法都表明这种说法是非法的
 * <li><em>IllegalStateException</em> -
 * to signal that call has good arguments but is not expected here (violation of contract) and for features/properties
 * 以表明这个电话有很好的论据，但这里并没有预料到（违反合同）以及特性/属性
 *    when requesting setting unimplemented feature/property
 *    请求设置未实现的特性/属性时
 *    (UnsupportedOperationException would be better but it is not in MIDP)
 *    （不支持的操作异常会更好，但不在MIDP中
 *  </ul>
 *
 * <p><b>NOTE:</b> writing  CDSECT, ENTITY_REF, IGNORABLE_WHITESPACE,
 *  PROCESSING_INSTRUCTION, COMMENT, and DOCDECL
 *  in some implementations may not be supported (for example when serializing to WBXML).
 *  在一些实现可能不支持(例如当序列化WBXML)。
 * In such case IllegalStateException will be thrown and it is recommended to use an optional feature to signal
 * 在这种情况下，将抛出非法状态异常，建议使用可选功能发送信号
 * that implementation is not supporting this kind of output.
 */

public interface XmlSerializer {

    /**
     * Set feature identified by name (recommended to be URI for uniqueness).
     * 设置名称标识的功能（推荐为唯一性的URI）
     * Some well known optional features are defined in
     * 一些众所周知的可选功能定义在
     * <a href="http://www.xmlpull.org/v1/doc/features.html">
     * http://www.xmlpull.org/v1/doc/features.html</a>.
     *
     * If feature is not recognized or can not be set then IllegalStateException MUST be thrown.
     *如果功能无法识别或无法设置，则必须抛出非法状态异常
     * @exception IllegalStateException If the feature is not supported or can not be set
     */
    void setFeature(String name,
                           boolean state)
        throws IllegalArgumentException, IllegalStateException;


    /**
     * Return the current value of the feature with given name.
     * <p><strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null
     *
     * @param name The name of feature to be retrieved.
     * @return The value of named feature.
     * @exception IllegalArgumentException if feature string is null
     */
    boolean getFeature(String name);


    /**
     * Set the value of a property.
     * (the property name is recommended to be URI for uniqueness).
     * Some well known optional properties are defined in
     * <a href="http://www.xmlpull.org/v1/doc/properties.html">
     * http://www.xmlpull.org/v1/doc/properties.html</a>.
     *
     * If property is not recognized or can not be set
     * then IllegalStateException MUST be thrown.
     *
     * @exception IllegalStateException if the property is not supported or can not be set
     */
    void setProperty(String name,
                            Object value)
        throws IllegalArgumentException, IllegalStateException;

    /**
     * Look up the value of a property.
     *
     * The property name is any fully-qualified（合格） URI. I
     * <p><strong>NOTE:</strong> unknown properties are <string>always</strong> returned as null
     *
     * @param name The name of property to be retrieved.
     * @return The value of named property.
     */
    Object getProperty(String name);

    /**
     * Set to use binary output stream with given encoding.
     * 设置为使用给定编码的二进制输出流
     */
    void setOutput (OutputStream os, String encoding)
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Set the output to the given writer.
     * <p><b>WARNING</b> no information about encoding is available!
     * 没有关于编码的信息！
     */
    void setOutput (Writer writer)
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Write &lt;&#63;xml declaration with encoding (if encoding not null) and standalone flag (if standalone not null)
     * 用编码写入＆lt;？xml声明（如果编码不为空）和独立标志（如果standalone不为空
     * This method can only be called just after setOutput.
     * 这个方法只能在set Output之后调用
     */
    void startDocument (String encoding, Boolean standalone)
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Finish writing.
     * All unclosed start tags will be closed and output will be flushed.
     * 所有未封闭的开始标签将被关闭，输出将被刷新
     * After calling this method no more output can be serialized until next call to setOutput()
     * 在调用这个方法之后，没有更多的输出可以被序列化，直到下一次调用Output（）
     */
    void endDocument ()
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Binds the given prefix to the given namespace.
     * ：将给定的前缀绑定到给定的名称空间
     * This call is valid for the next element including child elements.
     * 此调用对包含子元素的下一个元素有效
     * The prefix and namespace MUST be always declared even if prefix is not used in element (startTag() or attribute()) -
     * 即使元素中没有使用前缀，也必须始终声明前缀和名称空间（开始标记（）或属性（）） -
     * for XML 1.0 it must result in declaring <code>xmlns:prefix='namespace'</code>
     * (or <code>xmlns:prefix="namespace"</code> depending what character is used to quote attribute value).
     *
     * <p><b>NOTE:</b> this method MUST be called directly before startTag()
     *   and if anything but startTag() or setPrefix() is called next there will be exception.
     *   如果有的话，但启动标记（）或设置前缀（）接下来调用将有异常。
     * <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound
     *   and can not be redefined see:
     * <a href="http://www.w3.org/XML/xml-names-19990114-errata#NE05">Namespaces in XML Errata</a>.
     * <p><b>NOTE:</b> to set default namespace use as prefix empty string.
     *
     * @param prefix must be not null (or IllegalArgumentException is thrown)
     * @param namespace must be not null
     */
    void setPrefix (String prefix, String namespace)
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Return namespace that corresponds to given prefix
     * 返回与给定前缀对应的名称空间
     * If there is no prefix bound to this namespace return null but if generatePrefix is false then return generated prefix.
     *如果没有绑定到这个名称空间的前缀返回null，但是如果生成Prefix为false，则返回生成的前缀。
     * <p><b>NOTE:</b> if the prefix is empty string "" and default namespace is bound
     * to this prefix then empty string ("") is returned.
     *
     * <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound
     *   will have values as defined
     * <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML specification</a>
     */
    String getPrefix (String namespace, boolean generatePrefix)
        throws IllegalArgumentException;

    /**
     * Returns the current depth of the element.
     * Outside the root element, the depth is 0.
     * The depth is incremented by 1 when startTag() is called.
     * The depth is decremented （递减）after the call to endTag()
     * event was observed（观察者）.
     *
     * <pre>
     * &lt;!-- outside --&gt;     0
     * &lt;root&gt;               1
     *   sometext                 1
     *     &lt;foobar&gt;         2
     *     &lt;/foobar&gt;        2
     * &lt;/root&gt;              1
     * &lt;!-- outside --&gt;     0
     * </pre>
     */
    int getDepth();

    /**
     * Returns the namespace URI of the current element as set by startTag().
     *
     * <p><b>NOTE:</b> that means in particular（待定） that: <ul>
     * <li>if there was startTag("", ...) then getNamespace() returns ""
     * <li>if there was startTag(null, ...) then getNamespace() returns null
     * </ul>
     *
     * @return namespace set by startTag() that is currently in scope
     */
    String getNamespace ();

    /**
     * Returns the name of the current element as set by startTag().
     * It can only be null before first call to startTag()
     * or when last endTag() is called to close first startTag().
     *
     * @return namespace set by startTag() that is currently in scope
     */
    String getName();

    /**
     * Writes a start tag with the given namespace and name.
     * If there is no prefix defined for the given namespace,
     * a prefix will be defined automatically.
     * The explicit prefixes for namespaces can be established by calling setPrefix() immediately before this method.
     * 命名空间的显式前缀可以通过在该方法之前立即调用set Prefix（）来建立
     * If namespace is null no namespace prefix is printed but just name.
     * If namespace is empty string then serializer will make sure that
     * default empty namespace is declared (in XML 1.0 xmlns='')
     * or throw IllegalStateException if default namespace is already bound
     * to non-empty string.
     */
    XmlSerializer startTag (String namespace, String name)
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Write an attribute. Calls to attribute() MUST follow a call to
     * startTag() immediately. If there is no prefix defined for the
     * given namespace, a prefix will be defined automatically.
     * If namespace is null or empty string
     * no namespace prefix is printed but just name.
     */
    XmlSerializer attribute (String namespace, String name, String value)
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Write end tag.
     * Repetition of namespace and name is just for avoiding errors.
     * 命名空间和名称的重复只是为了避免错误
     * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were very difficult to find...
     * ：在K XML结束标签没有参数，不匹配的标签是很难找到..
     * If namespace is null no namespace prefix is printed but just name.
     * 如果名称空间为空，则不会打印名称空间前缀，而只是名称
     * If namespace is empty string then serializer will make sure that default empty namespace is declared (in XML 1.0 xmlns='').
     * 如果名称空间为空字符串，则序列化程序将确保声明默认的空名称空间（在XML 1.0 xmlns =''中）。
     */
    XmlSerializer endTag (String namespace, String name)
        throws IOException, IllegalArgumentException, IllegalStateException;


        /*
         * Writes a start tag with the given namespace and name.
         * 用给定的名称空间和名称写一个开始标记
         * <br />If there is no prefix defined (prefix == null) for the given namespace,
         * a prefix will be defined automatically.
         * <br />If explicit prefixes is passed (prefix != null) then it will be used
         * 如果显式前缀被传递（前缀！= null），那么它将被使用
          *and namespace declared if not already declared or  throw IllegalStateException the same prefix was already set on this  element (setPrefix()) and was bound to different namespace.
          * 和声明的名称空间，如果尚未声明或抛出非法状态异常相同的前缀已经设置在此元素（设置前缀（）），并被绑定到不同的命名空间
         * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
         * <br />If namespace is null then no namespace prefix is printed but just name.
         * <br />If namespace is empty string then serializer will make sure that
         * default empty namespace is declared (in XML 1.0 xmlns='')
         * or throw IllegalStateException if default namespace is already bound
         * to non-empty string.

        XmlSerializer startTag (String prefix, String namespace, String name)
            throws IOException, IllegalArgumentException, IllegalStateException;

        *
         * Write an attribute. Calls to attribute() MUST follow a call to
         * startTag() immediately.
         * <br />If there is no prefix defined (prefix == null) for the given namespace,
         * a prefix will be defined automatically.
         * <br />If explicit prefixes is passed (prefix != null) then it will be used
         * and namespace declared if not already declared or
         * throw IllegalStateException the same prefix was already set on this
         * element (setPrefix()) and was bound to different namespace.
         * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
         * <br />If namespace is null then no namespace prefix is printed but just name.
         * <br />If namespace is empty string then serializer will make sure that
         * default empty namespace is declared (in XML 1.0 xmlns='')
         * or throw IllegalStateException if default namespace is already bound
         * to non-empty string.

        XmlSerializer attribute (String prefix, String namespace, String name, String value)
            throws IOException, IllegalArgumentException, IllegalStateException;

        *
         * Write end tag. Repetition of namespace, prefix, and name is just for avoiding errors.
         * <br />If namespace or name arguments are different from corresponding startTag call
         * then IllegalArgumentException is thrown, if prefix argument is not null and is different
         * from corresponding starTag then IllegalArgumentException is thrown.
         * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
         * <br />If namespace is null then no namespace prefix is printed but just name.
         * <br />If namespace is empty string then serializer will make sure that
         * default empty namespace is declared (in XML 1.0 xmlns='').
         * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were
         *  very difficult to find...</p>

     ALEK: This is really optional as prefix in end tag MUST correspond to start tag but good for error checking
        XmlSerializer endTag (String prefix, String namespace, String name)
            throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Writes text, where special XML chars are escaped automatically
     */
    XmlSerializer text (String text)
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Writes text, where special XML chars are escaped automatically
     * 写入文本，其中特殊的XML字符自动转义
     */
    XmlSerializer text (char [] buf, int start, int len)
        throws IOException, IllegalArgumentException, IllegalStateException;

    void cdsect (String text)
        throws IOException, IllegalArgumentException, IllegalStateException;
    void entityRef (String text)  throws IOException,
        IllegalArgumentException, IllegalStateException;
    void processingInstruction (String text)
        throws IOException, IllegalArgumentException, IllegalStateException;
    void comment (String text)
        throws IOException, IllegalArgumentException, IllegalStateException;
    void docdecl (String text)
        throws IOException, IllegalArgumentException, IllegalStateException;
    void ignorableWhitespace (String text)
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
     * Write all pending output to the stream.
     * 将所有待处理的输出写入流中
     * If method startTag() or attribute() was called then start tag is closed (final &gt;) before flush() is called on underlying output stream.
     *如果方法start（）或者attribute（）被调用，那么在调用底层输出流的flush（）之前，关闭start标签（final＆gt;）
     * <p><b>NOTE:</b> if there is need to close start tag
     * 如果有需要关闭开始标记
     * (so no more attribute() calls are allowed) but without flushing output call method text() with empty string (text("")).
     *（所以不允许更多的属性（）调用），但没有清空输出调用方法文本（）与空字符串（文本（“”））。
     */
    void flush ()
        throws IOException;

}
